package webview

import (
	"encoding/json"
	"gitee.com/snxamdf/wui/logs"
	"gitee.com/snxamdf/wui/util"
	"gitee.com/snxamdf/wui/util/w"
	"html/template"
	"log"
)

type Callback func(msg string)

type Listen interface {
	Listen(wd RPCData)
	BindWidgetUpdateListen(wd RPCData)
	BindWidgetClickEventListen(wd RPCData, fn Callback)
	BindWidgetChangeEventListen(wd RPCData, fn Callback)
}

func Handler(msg string, ln Listen, cb Callback) {
	//logs.Info("接收消息处理", msg)
	rpc := RPCData{}
	if err := json.Unmarshal([]byte(msg), &rpc); err != nil {
		log.Println("sockjs 解析接收消息失败", err)
	} else {
		if rpc.Type == Update {
			//处理更新数据
			go ln.BindWidgetUpdateListen(rpc)
		} else if rpc.Type == EventClick {
			//处发事件 Click
			go ln.BindWidgetClickEventListen(rpc, cb)
		} else if rpc.Type == EventChange {
			//处发事件 change
			go ln.BindWidgetChangeEventListen(rpc, cb)
		}
	}
}

type RPCData struct {
	Type          TYPE   `json:"type"`
	ComponentName string `json:"componentName"`
	WidgetId      string `json:"widgetId"`
	Value         Data   `json:"value"`
}
type TYPE string

var (
	Update       TYPE = "update"
	UpdateResult TYPE = "updateResult"
	EventClick   TYPE = "click"
	EventChange  TYPE = "change"
	Init         TYPE = "init"
)

func CheckType(typ TYPE) bool {
	return typ == Update || typ == UpdateResult || typ == EventClick || typ == Init
}

func NewRPCData(typ TYPE, w WidgetInterface, value Data) *RPCData {
	if typ == "" {
		return nil
	}
	return &RPCData{
		Type:          typ,
		ComponentName: w.GetComponent().GetName(),
		WidgetId:      w.GetId(),
		Value:         value,
	}
}

func NewToRPC(data string) RPCData {
	rpc := RPCData{}
	if err := json.Unmarshal([]byte(data), &rpc); err != nil {
		logs.Error("NewToRPC", err)
		return rpc
	}
	return rpc
}

func (m RPCData) ValueJSON() string {
	r, _ := util.ToJson(m.Value)
	return string(r)
}

func (m RPCData) ValueWMap() (*w.WMap, error) {
	return w.ConvertByJSON(m.ValueJSON())
}

func (m RPCData) JSON() string {
	r, _ := util.ToJson(m)
	return string(r)
}

func (m RPCData) WMap() (*w.WMap, error) {
	return w.ConvertByJSON(m.JSON())
}

var rpcDataTemp = template.Must(template.New("rpcDataTemp").Parse(`GoBind.GoInvokeResult("{{.Type}}", "{{.ComponentName}}", "{{.WidgetId}}", "{{.Value}}");`))

func (m RPCData) Script() (string, error) {
	return util.HtmlTemplate(rpcDataTemp, m)
}
